package com.coin900.coin.server.fu.ctrl;

import com.coin900.coin.base.AjaxResponse;
import com.coin900.coin.base.BxConstants;
import com.coin900.coin.base.CoinConstants;
import com.coin900.coin.base.FuConstants;
import com.coin900.coin.base.restTemplate.BasicAuthRestTemplate;
import com.coin900.coin.base.utils.GoogleAuthenticator;
import com.coin900.coin.base.utils.RequestUtil;
import com.coin900.coin.persist.coin.CoinCoinVO;
import com.coin900.coin.persist.fu.*;
import com.coin900.coin.persist.sbi.SbiRateVO;
import com.coin900.coin.service.coin.ICoinCoinService;
import com.coin900.coin.service.fu.*;
import com.coin900.coin.service.sbi.ISbiRateService;
import com.value.exception.BusinessException;
import com.value.mybatis.Pagination;
import com.value.utils.FileUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * @author shui
 * @create 2017-12-20
 **/
@Controller
public class FuCapitalCtrl extends FuController {

    /**
     * 校验提现地址是否正确
     * 比如用户需要添加提现地址的时候, 应该对输入的地址做一次校验
     *
     * @param coinName
     * @param address
     * @return { isvalid: true/false }
     */
    @RequestMapping(value = "/withdraw-validateaddress", method = RequestMethod.GET)
    public Object validateaddress(@RequestParam String coinName,
                                  @RequestParam String address) {
        BasicAuthRestTemplate restTemplate = new BasicAuthRestTemplate(BxConstants.BX_BLOCK_CHAIN_BASIC_NAME, BxConstants.BX_BLOCK_CHAIN_BASIC_PASS);
        ResponseEntity<String> result = restTemplate.getForEntity(BxConstants.BX_BLOCK_CHAIN_VALIDATE_ADDRESS + "?" + "currency" + coinName + "&address=" + address, String.class);
        JSONObject jsonObject = JSONObject.fromObject(result.getBody());
        boolean isvalid = jsonObject.getBoolean("isvalid");
        return new ModelAndView().addObject("isvalid", isvalid);
    }

    /**
     * 充值提现历史记录
     *
     * @param viewType
     * @param type     1充值记录 2提现记录
     * @param request
     * @return
     */
    @RequestMapping(value = "/capital", method = RequestMethod.GET)
    public ModelAndView rechargeList(@RequestParam(required = false) String viewType,
                                     @RequestParam Integer type,
                                     HttpServletRequest request) {

        if (CoinConstants.COIN_PAGE.equals(viewType)) {
            ModelAndView modelAndView = super.buildView(request, "project/subsidiary");
            return modelAndView;
        }

        FuUserVO user = super.getUser();
        AjaxResponse response = super.buildAjaxResponse(request);
        Pagination pagination = RequestUtil.buildPage(request);
        Map<String, Object> params = pagination.getParams();
        params.put("dataStatus", 1);
        params.put("userId", user.getId());

        if (type == 1) {
            // 充值记录
            List<FuCapitalRechargeVO> rechargeList = this.rechargeService.loadFuCapitalRechargeForPage(pagination);
            if (!rechargeList.isEmpty()) {
                for (FuCapitalRechargeVO fuCapitalRechargeVO : rechargeList) {
                    Integer transferStatus = fuCapitalRechargeVO.getTransferStatus();
                    if (CoinConstants.COIN_CAPITAL_CONFIRM_SUCCESS == transferStatus) {
                        fuCapitalRechargeVO.setTransferStatusName("成功");
                    } else {
                        fuCapitalRechargeVO.setTransferStatusName("进行中");
                    }
                }
                pagination.setResults(rechargeList);
            }
        } else {
            // 提现记录
            List<FuCapitalWithdrawVO> withdrawList = this.withdrawService.loadFuCapitalWithdrawForPage(pagination);
            if (!withdrawList.isEmpty()) {
                for (FuCapitalWithdrawVO fuCapitalWithdrawVO : withdrawList) {
                    Integer checkStatus = fuCapitalWithdrawVO.getCheckStatus();
                    fuCapitalWithdrawVO.setCheckStatusName(CoinConstants.COIN_CHECK_STATUS.get(checkStatus));
                    Integer transferStatus = fuCapitalWithdrawVO.getTransferStatus();
                    if (transferStatus != null) {
                        if (transferStatus == CoinConstants.COIN_CAPITAL_CONFIRM_SUCCESS) {
                            fuCapitalWithdrawVO.setCheckStatusName("提现成功");
                        } else {
                            fuCapitalWithdrawVO.setCheckStatusName("提现中");
                        }
                    }
                }
                pagination.setResults(withdrawList);
            }
        }

        response.addPagination(pagination);
        return response.getMav();
    }

    /**
     * 提现申请
     *
     * @param withdrawVO
     * @param request
     * @return
     */
    @RequestMapping(value = "/capital-withdraw", method = RequestMethod.POST)
    public ModelAndView withdrawPost(@RequestBody FuCapitalWithdrawVO withdrawVO,
                                     HttpServletRequest request) {

        FuUserVO user = super.getUser();
        FuUserVO dbUser = this.userService.getUser(user.getId());
        String mobile = dbUser.getMobile();
        String key = CoinConstants.COIN_SMS_CODE_WITHDRAW;

        if(dbUser.getIdcardStatus() != 1){
            throw new BusinessException("请先进行实名认证");
        }

        //提现验证
        // type 1短信验证  2谷歌验证

        if(StringUtils.isBlank(withdrawVO.getVerifyCode())){
            throw new BusinessException("验证码不能为空");
        }
        if(withdrawVO.getVerifyType()==FuConstants.VERIFY_TYPE_SMS){
            if (!this.verifyCode(withdrawVO.getVerifyCode(), key, mobile)) {
                throw new BusinessException("验证码错误");
            }
        }else{
            Long code=Long.parseLong(withdrawVO.getVerifyCode());
            Boolean verify = GoogleAuthenticator.verify(code, user.getGoogleSecret());
            if (!verify) {
                throw new BusinessException("验证码错误");
            }
        }

        AjaxResponse response = super.buildAjaxResponse(request);
        Long userId = user.getId();
        Long coinId = withdrawVO.getCoinId();
        Double balance = withdrawVO.getBalance();
        if (balance <= 0) {
            throw new BusinessException("充值金额不能为空");
        }

        // 校验账户余额是否足够提现
        FuUserWalletVO userWallet = this.walletService.getUserWallet(userId, coinId);
        Double available = userWallet.getAvailable();
        if (available < balance) {
            // 可用余额少于申请值
            throw new BusinessException("余额不足");
        }
        String address = userWallet.getAddress();
        if (StringUtils.isBlank(address)) {
            throw new BusinessException("请填写充值地址");
        }

        /***** 此处可能需要计算有没有超过单日的最高限额，但是根据需求现在不做要求 *****/

        // 获取服务费率
        SbiRateVO sbiRate = this.rateService.getSbiRate(coinId);
        if (sbiRate == null) {
            throw new BusinessException("后台未设置服务费率");
        }
        // 检验提现数量是否大于最低提现额度，是否小于最高体提现额度
        if (balance < sbiRate.getMinBalance()) {
            throw new BusinessException("提现金额低于单笔下限");
        }
        if (balance > sbiRate.getMaxBalance()) {
            throw new BusinessException("提现金额高于单笔上限");
        }

        // 设置矿工费
        Double withdrawRate = sbiRate.getWithdrawRate();
        withdrawVO.setCost(withdrawRate);
        // 设置其他参数
        withdrawVO.setAddress(address);
        withdrawVO.setCreatedInfor(user);
        withdrawVO.setCheckStatus(FuConstants.FU_CHECK_STATUS_ING);

        FuUserWalletVO fuUserWalletVO = new FuUserWalletVO();
        fuUserWalletVO.setUserId(userId);
        fuUserWalletVO.setCoinId(coinId);
        fuUserWalletVO.setAvailable(balance);
        fuUserWalletVO.setBlocked(balance);
        fuUserWalletVO.setModifiedInfor(user);

        // 在 capital_depital 中新增一条记录
        FuCapitalDetailVO fuCapitalDetailVO = new FuCapitalDetailVO();
        fuCapitalDetailVO.setUserId(userId);
        fuCapitalDetailVO.setType(2);
        fuCapitalDetailVO.setAddress(address);
        fuCapitalDetailVO.setCreatedInfor(user);

        this.withdrawService.doCreateFuCapitalWithdraw(withdrawVO, fuUserWalletVO, fuCapitalDetailVO);
        return response.getMav();
    }

    /**
     * 充值-获取一个充值地址
     *
     * @param coinId
     * @param request
     * @return
     */
    @RequestMapping(value = "/recharge-get-address", method = RequestMethod.GET)
    public ModelAndView getRechargeAddress(@RequestParam Long coinId,
                                           HttpServletRequest request) {
        FuUserVO user = super.getUser();
        Long userId = user.getId();
        CoinCoinVO coin = this.coinCoinService.getCoin(coinId);
        String coinName = coin.getCoinName();
        FuUserWalletVO userWallet = this.walletService.getUserWallet(userId, coinId);
        // 提现地址
        String address = null;
        if (userWallet == null) {
            // 获取一个地址
            address = this.getNewAddress(coinName);
            FuUserWalletVO fuUserWalletVO = new FuUserWalletVO();
            fuUserWalletVO.setUserId(userId);
            fuUserWalletVO.setCoinId(coinId);
            fuUserWalletVO.setBalance(0d);
            fuUserWalletVO.setBlocked(0d);
            fuUserWalletVO.setAvailable(0d);
            fuUserWalletVO.setCreatedInfor(user);
            fuUserWalletVO.setAddress(address);
            this.walletService.insertFuUserWallet(fuUserWalletVO);
        } else {
            String dbAddress = userWallet.getAddress();
            if (StringUtils.isBlank(dbAddress)) {
                // 获取一个新地址
                address = this.getNewAddress(coinName);
                userWallet.setAddress(address);
                this.walletService.updateFuUserWallet(userWallet);
            } else {
                address = dbAddress;
            }
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("address", address);
        return modelAndView;
    }

    @RequestMapping(value = "/recharge-basecode", method = RequestMethod.GET)
    public ModelAndView getRechargeAddress(@RequestParam String address,
                                           HttpServletRequest request) {
        String baseCode = com.coin900.coin.base.utils.FileUtils.encode(address.toString(), 300, 300);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("baseCode", baseCode);
        return modelAndView;
    }

    /**
     * 生成一个对应币种的新地址 (分配给 User 对应币种的 Wallet)
     *
     * @param coinName 币种的名字，小写
     * @return 返回币种对应的地址 { address: 'xxx' }
     */
    private String getNewAddress(String coinName) {
        BasicAuthRestTemplate restTemplate = new BasicAuthRestTemplate(BxConstants.BX_BLOCK_CHAIN_BASIC_NAME, BxConstants.BX_BLOCK_CHAIN_BASIC_PASS);
        ResponseEntity<String> result = restTemplate.getForEntity(BxConstants.BX_BLOCK_CHAIN_GET_ADDRESS + coinName, String.class);
        JSONObject jsonObject = JSONObject.fromObject(result.getBody());
        String address = jsonObject.getString("address");
        return address;
    }

    /**
     * 校验验证码是否正确
     *
     * @param code   用户输入的验证码
     * @param key    redis 中对应的 key
     * @param mobile 用户手机号
     * @return
     */
    private boolean verifyCode(String code, String key, String mobile) {
        String redisCode = (String) this.redisTemplate.opsForValue().get(key + mobile);
        if (redisCode==null||!code.equals(redisCode)) {
            return false;
        } else {
            return true;
        }
    }

    @Autowired
    private ISbiRateService rateService;
    @Autowired
    private IFuCapitalRechargeService rechargeService;
    @Autowired
    private IFuCapitalWithdrawService withdrawService;
    @Autowired
    private IFuUserWalletService walletService;
    @Autowired
    private ICoinCoinService coinCoinService;
    @Autowired
    private IFuUserService userService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
}
